
#ifndef __SQLITE_DB_H
#define __SQLITE_DB_H

#include <vector>
#include <sqlite3.h>
#include "../iface/debug.h"

// Maybe write in hourly backups somewhere?

/** An interface to an SQLite3 database.
 * 
 * For thread safety a mutex is given to globally lock the database during
 * SQL execution. The class gives both thread safe and unsafe methods so that
 * it is possible for external caller to use the same sqlite3_mutex_enter and
 * splite3_mutex_leave calls to enforce operation atomicity externally, helping
 * to keep a consistent state across multiple tables and even possibly
 * multiple databases. */
class SQLiteDB
{
   public:
      SQLiteDB(const char *filename, int persists);
      ~SQLiteDB();
      int sqlInstantExec(const char *query);
      int sqlInstantExec_unsafe(const char *query);
      int sqlInstantExecf(const char *query, ...);
      int sqlInstantExecf_unsafe(const char *query, ...);
      std::vector<char *> *sqlScanRowText(const char *csql);
      std::vector<char *> *sqlScanRowText_unsafe(const char *csql);
      std::vector<char *> *sqlScanRowTextf(const char *csql, ...);
      std::vector<char *> *sqlScanRowTextf_unsafe(const char *csql, ...);
      std::vector<char *> *sqlScanAllText(const char *csql);
      std::vector<char *> *sqlScanAllTextf(const char *csql, ...);
      void backup();
      static int isWhitespace(char wht);
      static void stringSanitiser(char *sanstr);
      void ensureTablesAreCreated(int notables, ...);
      int sqlGetSingleIntf_unsafe(int *result, const char *csql, ...);
      int sqlGetSingleDoublef_unsafe(double *result, const char *csql, ...);
      int sqlGetSingleStringf_unsafe(char **result, const char *csql, ...);
      int sqlGetSingleIntf(int *result, const char *csql, ...);
      int sqlGetSingleDoublef(double *result, const char *csql, ...);
      int sqlGetSingleStringf(char **result, const char *csql, ...);
   protected:
      /** The main database pointer from SQLite3. */
      sqlite3 *db;
      /** The main database mutex from SQLite3. */
      sqlite3_mutex *dbmutex;
      /** The file name for SQL commands to clone the database to be dumped
       * to in an effort to provide a backup. */
      char *dumpfilename;
   private:
      int dumpDatabaseToSQL(const char *filename);
      int dumpTableToSQL(FILE *FP, const char *tablename);
      int loadSQL(const char *filename);
      int sqlScanRow_unsafe(sqlite3_stmt *sql, const char *rowformat, ...);
      std::vector<char *> *sqlScanRowText_unsafe(sqlite3_stmt *sql);
      std::vector<char *> *sqlScanAllText_unsafe(sqlite3_stmt *sql);
      int sqlGetSingleInt_unsafe(int *result, sqlite3_stmt *sql);
      int sqlGetSingleDouble_unsafe(double *result, sqlite3_stmt *sql);
      int sqlGetSingleString_unsafe(char **result, sqlite3_stmt *sql);
      sqlite3_stmt *sqlCompile(const char *query);
      int sqlFinalize(sqlite3_stmt *sql);
};

#endif
